package com.handpay.framework.swiper;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.TimeoutException;

import android.content.Context;
import android.text.TextUtils;

import com.bbpos.cswiper.CSwiperController;
import com.handpay.framework.swiper.ic.IShowSelectApplication;
import com.handpay.framework.utils.CommonUtils;
import com.handpay.zztong.hp.config.ZZTConstant;
import com.handpay.zztong.hp.log.HPLog;

/**
 * Created by jmshuai on 2014/8/15.
 */
class GjackSwiper extends AbstractBbposSwiper implements CSwiperController.CSwiperStateChangedListener {
    private static final String TAG = GjackSwiper.class.getSimpleName();
    private CSwiperController mSwipeController;
    private String mData;
    private SwipeResult mSwipeResult;
    private static final double VOLTAGELOWEST = 2.9d;
    //增加电量低通知
    protected IShowSelectApplication mSelectApplication;
    private volatile boolean			mIsSwiperOK				= true;

    public GjackSwiper(Context c,IShowSelectApplication mSelectApplication) {
        mLock = new AsynSwiperLock();
        mSwipeController = CSwiperController.createInstance(c, this);
        mSwipeController.setDetectDeviceChange(true);
        this.mSelectApplication = mSelectApplication;
        mIsSwiperOK = true;
    }
    
    @Override
    public String getCSN() {
        if (mSwipeController.getCSwiperState() == CSwiperController.CSwiperControllerState.STATE_IDLE) {
            mData = null;
            mSwipeController.exchangeAPDU("00b082000a");
            try {
                mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.GETCSN);
            } catch (TimeoutException te) {
                HPLog.i(TAG, "" ,te);
            }
            return mData;
        } else {
            //如果状态不对，等待200ms.
            try {
                Thread.sleep(200);
            } catch (InterruptedException ie) {
                HPLog.i(TAG, "" ,ie);
            }
        }
        return null;
    }

    @Override
    public boolean stopOperation() {
        if (mSwipeController.getCSwiperState() != CSwiperController.CSwiperControllerState.STATE_IDLE) {
            mSwipeController.stopCSwiper();
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean closeDevice() {
    	mIsSwiperOK = false;
    	mSelectApplication = null;
        if (null != mSwipeController) {
            mSwipeController.deleteCSwiper();
            mSwipeController = null;
        }
        return true;
    }

    @Override
    public SwipeResult swipeCard(String factor, int timeout) {
        mSwipeResult = new SwipeResult(SwipeStatus.SWIPE_ERROR);
        if (mSwipeController.getCSwiperState() == CSwiperController.CSwiperControllerState.STATE_IDLE) {
            mHTData.clear();
            mSwipeController.startCSwiperWithRandomNumber(factor);
            try {
                mLock.lock(timeout, AsynSwiperLock.NEW_SWIPE_CARD);
            } catch (TimeoutException te) {
                HPLog.e(TAG, "", te);
            }
        } else {
            //状态不对。直接返回
        }
        return mSwipeResult;
    }
    
    private void getBatteryVoltage(){
    	String bVoltage = mSwipeController.getBatteryVoltage();
    	HPLog.e(TAG, ":bVoltage--"+bVoltage);
    	if(!TextUtils.isEmpty(bVoltage)){
    		 try {
	    		if(Double.parseDouble(bVoltage) < VOLTAGELOWEST){
	    			if (null != mSelectApplication && mSelectApplication instanceof SwiperCallback) {
	    				((SwiperCallback) mSelectApplication).onBatteryLow();
	    			}
	        	}
    		 } catch (Exception te) {
                 HPLog.e(TAG, "", te);
             }
    	}
    }
    @Override
    public String encData(String data, String index, String factor) {
        HPLog.i(TAG, "data:" + data + " index:" + index + " factor:" + factor);
        mData = null;
        String time = factor.substring(0, factor.length() -2);
        HashMap<Integer, String[]> example = new HashMap<Integer, String[]>();
        try {
            if (ISwiperListener.MacDataIndex.equals(index)) {
                char[] mac = data.toCharArray();
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                try {
                    bos.write(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                            0x00, 0x00});
                    bos.write(String.valueOf(mac).getBytes());
                    bos.write(0x80);
                    while (bos.size() % 8 != 0) {
                        bos.write(0x00);
                    }
                    byte[] dataBytes = bos.toByteArray();
                    bos.close();
                    for (String partMac : formatMacString(dataBytes)) {
                        HashMap<Integer, String[]> hashMap = new HashMap<Integer,String[]>(1);
                        hashMap.put(SINGLE_ENC_MAC_KEY, new String[]{"15", time, partMac});
                        mData = null;
                        mSwipeController.batchExchangeAPDU(hashMap);
                        mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_MAC);
                        HPLog.i(TAG, partMac + " macResult: " + mData);
                        if (null != mData && mData.endsWith("9000")) {
                            //成功。去掉9000。中间返回是9000，mData就是“”，最后的话，mData就是算出来的mac
                            mData = mData.substring(0, mData.length() - 4).toUpperCase();
                        } else {
                            //失败了。设置mac加密失败。并退出循环
                            mData = null;
                            break;
                        }
                    }
                } catch (IOException ioe) {
                    HPLog.e(TAG, "" ,ioe);
                }
            } else if (ISwiperListener.KeyDataIndex.equals(index)){
                String cmd = formatDataAdpu(data);
                HPLog.i(TAG, "13 cmd:" + cmd);
                example.put(SINGLE_ENC_DATA_KEY, new String[]{"13", time, cmd});
                mSwipeController.batchExchangeAPDU(example);
                mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
            } else if (PIN_INDEX.equals(index)) {
                example.put(SINGLE_ENC_DATA_KEY, new String[] { "14", time, "80fa00000806" + data + "ffffffff" });
                mSwipeController.batchExchangeAPDU(example);
                mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
            }
        } catch (TimeoutException te) {
            HPLog.i(TAG,"",te);
        }
        return mData;
    }

    @Override
    public boolean isSwiperReady() {
        return mIsSwiperOK;
    }

    @Override
    public SwiperModel getSwiperModel() {
        return SwiperModel.GJACK_VOICE_MAG;
    }

//------------------------------------下面代码是有关智嘉刷卡器的代码
    /**
     *
     */
    @Override
    public void onWaitingForCardSwipe() {
        HPLog.i(TAG, "onWaitingForCardSwipe--------------");
//        getBatteryVoltage();
    }

    @Override
    public void onCardSwipeDetected() {
        HPLog.i(TAG, "onCardSwipeDetected--------------");
    }

    @Override
    public void onDecodeCompleted(HashMap<String, String> decodeData) {
        HPLog.i(TAG, "onDecodeCompleted--------------"+decodeData.toString());
        String encTrack2local = decodeData.get("encTrack2");
        String randomNumber = decodeData.get("randomNumber");
        String maskedPAN = decodeData.get("maskedPAN");
        if (TextUtils.isEmpty(String.valueOf(encTrack2local)) || TextUtils.isEmpty(randomNumber) || TextUtils.isEmpty(maskedPAN)) {
        	mSwipeResult = new SwipeResult(SwipeStatus.SWIPE_ERROR);
        } else {
            //刷卡的时候，记录二磁道，dynamicKey, 还有卡号明文.
            //其他的，譬如pin,卡号密文，金额密文等。输入密码后，做加密后加入。
        	
//        	08-18 21:00:21.296: I/hp(15733): GjackSwiper:onDecodeCompleted--------------
//        	{track3Length=0, randomNumber=8DAA0A5808B4F07D, track2Length=32, expiryDate=2003, formatID=46,
//        			encTrack2=32E285218782950B441E756203712D8337, ksn=B0ECF4CE494351920100, maskedPAN=5201690114432390}
        	//新版2.0.0 expiryDate
        	String expireDate = decodeData.get("expiryDate");
        	
			if (CommonUtils.checkExpireDate(expireDate)) {
				expireDate = expireDate.substring(0, 4);
				HPLog.i(HPLog.FDL_TAG, "GjackSwiper  -- plainExpireDate:"+expireDate);
				mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, expireDate);
			} else {
				HPLog.i(TAG, "GjackSwiper IC card but no plainExpireDate");
			}
        	
            mHTData.put(IBusinessSwiper.BANK_TRACK2_KEY, BusinessSwiper.autoFillTrack2(encTrack2local.toUpperCase(Locale.US)));
            mHTData.put(IBusinessSwiper.BANK_DYNAMIC_KEY, randomNumber.toUpperCase(Locale.US));
            mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY, maskedPAN);
            mSwipeResult = new SwipeResult(SwipeStatus.SWIPE_OK, maskedPAN);
        }
        mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
    }

    @Override
    public void onDecodeError(CSwiperController.DecodeResult decodeResult) {
        HPLog.i(TAG, "onDecodeError--------------" + decodeResult);
        mLock.unlock(AsynSwiperLock.IDLE);
    }

    @Override
    public void onError(int i, String s) {
        HPLog.i(TAG, "onError--------------" + i + " " + s);
        mLock.unlock(AsynSwiperLock.IDLE);
    }

    @Override
    public void onInterrupted() {
        HPLog.i(TAG, "onInterrupted--------------");
        if (AsynSwiperLock.NEW_SWIPE_CARD == mLock.getCurrrentCmdType()) {
            //stopCSwiper以及拔掉刷卡器，都会走onInterrupted
            HPLog.i(TAG, "cancel swipeCard");
            mSwipeResult = new SwipeResult(SwipeStatus.SWIPE_CANCEL);
        }
        mLock.unlock(AsynSwiperLock.IDLE);
    }

    @Override
    public void onNoDeviceDetected() {
        HPLog.i(TAG, "onNoDeviceDetected--------------");
    }

    @Override
    public void onTimeout() {
        HPLog.i(TAG, "onTimeout--------------");
        mLock.unlock(AsynSwiperLock.IDLE);
    }

    @Override
    public void onWaitingForDevice() {
        HPLog.i(TAG, "onWaitingForDevice--------------");
    }

    @Override
    public void onDevicePlugged() {
        HPLog.i(TAG, "onDevicePlugged--------------");
    }

    @Override
    public void onDeviceUnplugged() {
        HPLog.i(TAG, "onDeviceUnplugged--------------");
    }

    @Override
    public void onApduResponseReceived(String s) {
        HPLog.i(TAG, "onApduResponseReceived--------------");
        mData = s.substring(0, s.length() - 4).toUpperCase();
        //获取csn会走到这里
        mLock.unlock(AsynSwiperLock.GETCSN);
    }

    @Override
    public void onBatchApduResponseReceived(HashMap<Integer, String> data) {
        HPLog.i(TAG, "onBatchApduResponseReceived--------------");
        //单独加密数据的返回结果
        if (null != data.get(SINGLE_ENC_DATA_KEY)) {
            mData = data.get(SINGLE_ENC_DATA_KEY).substring(0, data.get(SINGLE_ENC_DATA_KEY).length() - 4).toUpperCase(Locale.US);
            mLock.unlock(AsynSwiperLock.CACL_DATA);
        } else if (null != data.get(SINGLE_ENC_MAC_KEY)) {
            //单独做mac的数据返回
            HPLog.i(TAG, "onBatchApduResponseReceived--------------" + data.get(SINGLE_ENC_MAC_KEY));
            mData = data.get(SINGLE_ENC_MAC_KEY);
            mLock.unlock(AsynSwiperLock.CACL_MAC);
        } else {

        }
    }

    @Override
    public void onGetKsnCompleted(String s) {
        HPLog.i(TAG, "onGetKsnCompleted--------------" + s);
    }

    @Override
    public void onReturnPinPadMappingFromViPOS(String s) {
        HPLog.i(TAG, "onReturnPinPadMappingFromViPOS--------------" + s);
    }

    @Override
    public void onReturnEPBFromViPOS(String s) {
        HPLog.i(TAG, "onReturnEPBFromViPOS--------------" + s);
    }
   
    
}
